NOTE
3.3 InnoDB redo log
1. redo log是什么 - MySQL InnoDB存储引擎的日志,用于崩溃恢复 - redo log是一种基于磁盘的数据结构,在崩溃恢复期间用于纠正不完整事务写入的数据 2. 为什么需要redo log - 根据持久性的要求,事务一旦commit完成那么就必须落盘保存。有两种方案 - 一种是
这是历史学习笔记,可能存在过时或不完整的理解。
1. redo log是什么
- MySQL InnoDB存储引擎的日志,用于崩溃恢复
- redo log是一种基于磁盘的数据结构,在崩溃恢复期间用于纠正不完整事务写入的数据
2. 为什么需要redo log
- 根据持久性的要求,事务一旦commit完成那么就必须落盘保存。有两种方案
- 一种是在事务提交commit完成之前把该事务所修改的所有页面都刷新到磁盘。但是这种方案性能会很差
- 另一种是日志,把修改了哪些页的哪些东西记录一下就好,commit完成之前把这个日志写入磁盘。这个日志数据量特别小并且是顺序IO
3. WAL
- Write-Ahead Logging:先写日志,再写磁盘

- redo log 包括两部分:一个是内存中的日志缓冲( redo log buffer ),另一个是磁盘上的日志文件(redo log)
- 服务器启动时就向操作系统申请了一大片称之为 redo log buffer 的连续内存空间
- mysql 每执行一条 DML 语句,先将记录append到redo log buffer中
- 某个时机把log buffer刷入磁盘
- log buffer空间不足
- 事务提交
- 后台线程每秒刷新一次
- 正常关闭服务器时
- checkpoint
4. 日志格式

- 底层使用循环数组实现
- WritePos->CheckPoint是空闲的,CheckPoint->WritePos是未刷入磁盘的数据
5. redo log的写入机制

- 事务在执行过程中,生成的redo log是要先写到redo log buffer的
innodb_flush_log_at_trx_commit参数- 设置为0的时候,表示每次事务提交时都只是把redo log留在redo log buffer中;
- 设置为1的时候,表示每次事务提交时都将redo log直接持久化到磁盘;
- 设置为2的时候,表示每次事务提交时都只是把redo log写到page cache。
- 后台线程
- 每隔1s会write+fsync
- redo log buffer占用的空间即将达到 innodb_log_buffer_size一半的时候,后台线程会主动写盘
- 组提交
- 给每个redo-log分配一个LSN,多个并发的事务的redo-log一起fsync,同时可以一起fsync bin-log
6. redo-log vs bin-log
| redo-log | bin-log | |
|---|---|---|
| 层次 | 存储引擎层,InnoDB特有 | Server层,所有引擎都可以使用 |
| 日志格式 | 物理日志,记录的是“在某个数据页上做了什么修改”。参考分布式系统复制.md | 逻辑日志,记录的是这个语句的原始逻辑,比如“给ID=2这一行的c字段加1 ” 。参考分布式系统复制.md |
| 写入方式 | 循环写。空间固定会用完 | 追加写。binlog文件写到一定大小后会切换到下一个,并不会覆盖以前的日志 |
7. 如何保证redo-log和bin-log的一致性
7.1. 两阶段提交

- 写入redo-log,处于prepare状态
- 写入bin-log
- 提交事务,redo-log处于commit状态 以下说明都是在内存中的情况: 如果MySQL在时刻A宕机了,重启进行崩溃恢复,发现redo-log处于prepare状态,bin-log还没写,直接回滚 如果MySQL在时刻B宕机了,重启进行崩溃恢复,发现redo-log处于prepare状态,bin-log已经写了,那么需要校验bin-log的完整性,如果完整那么直接提交 如果MySQL在时刻C宕机了,重启进行崩溃恢复,发现redo-log处于commit状态,那么表明redo-log和bin-log是完整的,直接提交